package cn.hdmis.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import cn.hdmis.bean.QueryResult;
import cn.hdmis.dao.BaseDao;
import cn.hdmis.util.GenericsUtils;
import cn.hdmis.util.ObjectUtil;

/**
 * @author penwei
 * 
 */

public class BaseDaoImp<T> extends HibernateDaoSupport implements BaseDao<T> {
	private Class<T> entityClass;
	private String entityClassName;
	@SuppressWarnings("unchecked")
	public BaseDaoImp() {
		this.entityClass = GenericsUtils.getSuperClassGenricType(getClass());
		this.entityClassName = this.entityClass.getSimpleName();
		logger.debug("BaseDaoImp GenericsUtils.getSuperClassGenricType  entityClass:"+entityClass);
	}

	@Override
	public void save(T entity) {
		try {
			super.getHibernateTemplate().save(entity);
		} catch (DataAccessException e) {
			e.printStackTrace();
			throw e;
		}
	}
	@Override
	public void saveOrUpdate(T entity) {
		try {
			super.getHibernateTemplate().saveOrUpdate(entity);
		} catch (DataAccessException e) {
			throw e;
		}
	}
	@Override
	public void update(T entiey) {
		super.getHibernateTemplate().update(entiey);
	}

	@SuppressWarnings("unchecked")
	public List<T> findByEntity(Object entiey)
	{
		return super.getHibernateTemplate().findByExample(entiey);
	}

	@SuppressWarnings("unchecked")
	public List<T> findByProperty(String propertyName, Object value)
	{
		String queryString = "from " + entityClassName + " o where o." + propertyName + "= ?";
		return super.getHibernateTemplate().find(queryString, value);
	}

	public T findByID(Serializable entityId)
	{
		try{
		if (null != entityId)
			return (T) super.getHibernateTemplate().get(entityClass, entityId);
		}catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final String wherejpql, final Object[] queryParams,
			final List<String> orderby)
	{
		final QueryResult<T> queryResult = new QueryResult<T>();

		super.getHibernateTemplate().execute(new HibernateCallback<T>()
		{
			@SuppressWarnings("unchecked")
			public T doInHibernate(Session session) throws HibernateException, SQLException
			{
				String hql = "from " + entityClassName + " o " + (wherejpql == null || "".equals(wherejpql.trim()) ? "" : " where " + wherejpql)
						+ buildOrderby(orderby);
				Query query = session.createQuery(hql);
				setQueryParams(query, queryParams);// where
				queryResult.setTotalRecord(query.list().size());// first get size

				if (firstindex != -1 && maxresult != -1){
					query.setFirstResult(firstindex).setMaxResults(maxresult);
				}// last page

				queryResult.setResultList(query.list());

				return null;
			}

		});

		return queryResult;

	}
	public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final Map<String, Object> queryParamsMap,
			final List<String> orderby)
	{
		final QueryResult<T> queryResult = new QueryResult<T>();

		super.getHibernateTemplate().execute(new HibernateCallback<T>()
		{
			@SuppressWarnings("unchecked")
			public T doInHibernate(Session session) throws HibernateException, SQLException
			{
				String hql = "from " + entityClassName + " o " + buildQueryParams(queryParamsMap) + buildOrderby(orderby);
				Query query = session.createQuery(hql);
				setQueryParams(query, queryParamsMap);// where
				try {
					queryResult.setTotalRecord(query.list().size());// first get size
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (firstindex != -1 && maxresult != -1){
					query.setFirstResult(firstindex).setMaxResults(maxresult);
				}// last page

				queryResult.setResultList(query.list());

				return null;
			}

		});

		return queryResult;

	}
	@SuppressWarnings("unchecked")
	public QueryResult<T> getScrollDataCriteria(final int firstindex, final int maxresult, final Map<String, Object> queryParamsMap,
			final List<String> orderby){
		final QueryResult<T> queryResult = new QueryResult<T>();
		super.getHibernateTemplate().execute(new HibernateCallback<T>()
				{
					@SuppressWarnings("unchecked")
					public T doInHibernate(Session session) throws HibernateException, SQLException
					{
						Criteria criteria = session.createCriteria(entityClass);
						criteria.setMaxResults(maxresult);
						criteria.setFirstResult(firstindex);

						List rsList = criteria.list();
						queryResult.setResultList(rsList);
						return null;
					}

				});
		return queryResult;
	}

	
	public QueryResult<T> getScrollData(int firstindex, int maxresult, String wherejpql, Object[] queryParams)
	{
		return getScrollData(firstindex, maxresult, wherejpql, queryParams, null);
	}

	public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final  List<String> orderby)
	{
		return getScrollData(firstindex, maxresult, null, null, orderby);

	}
	
	public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final Map<String, Object> queryParamsMap)
	{
		return getScrollData(firstindex, maxresult, queryParamsMap, null);

	}
	public QueryResult<T> getScrollData(final int firstindex, final int maxresult)
	{
		return getScrollData(firstindex, maxresult, null, null, null);
	}

	public QueryResult<T> getScrollData()
	{
		return getScrollData(-1, -1, null, null, null);
	}



	/**
	 * 设置HQL里边的属性值
	 * 
	 * @param query
	 * @param queryParams
	 */
	protected static void setQueryParams(Query query, Object[] queryParams)
	{
		if (queryParams != null && queryParams.length > 0)
		{
			for (int i = 0; i < queryParams.length; i++)
			{
				query.setParameter(i, queryParams[i]);// 从0开始
			}
		}
	}
	
	protected static void setQueryParams(Query query,final Map<String, Object> queryParamsMap)
	{
		if (queryParamsMap != null && queryParamsMap.size() > 0)
		{
			Object[] keySet  =  queryParamsMap.keySet().toArray();
			for(int i = 0; i < keySet.length; i++)
			{
				query.setParameter(i, queryParamsMap.get(keySet[i]));
			}
		}
	}
	/**
	 * 设置HQL里边的属性值
	 * 
	 * @param query
	 * @param queryParamsMap
	 */
	protected static String buildQueryParams( final Map<String, Object> queryParamsMap)
	{
		StringBuffer paramsSQL = new StringBuffer("");
		if(queryParamsMap != null && queryParamsMap.size() > 0){
			paramsSQL.append(" Where ");
			for (String key : queryParamsMap.keySet())
			{
				paramsSQL.append(" o.").append(key).append(" = ? and ");
			}
			paramsSQL.append(" 1=1");
		}
		return paramsSQL.toString();
	}

	/**
	 * 组装order by语句
	 * 
	 * @param orderby
	 * @return
	 */
	protected static String buildOrderby(List orderby)
	{
		StringBuffer orderbyql = new StringBuffer("");
		if (orderby != null && orderby.size() > 0)
		{
			orderbyql.append(" order by ");
			for (Object order : orderby)
			{
				orderbyql.append("o.").append(order).append(",");
			}
			orderbyql.deleteCharAt(orderbyql.length() - 1);
		}
		return orderbyql.toString();
	}


	@SuppressWarnings("unchecked")
	@Override
	public List<T> findAllEntity() {
		try {
			DetachedCriteria dc = DetachedCriteria.forClass(entityClass); 
			return super.getHibernateTemplate().findByCriteria(dc);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public void deleteEntiey(T entiey){
		super.getHibernateTemplate().delete(entiey);
	}
	@Override
	public void delete(Serializable id) {
		T entiey = findByID(id);
		super.getHibernateTemplate().delete(entityClassName, entiey);
	}


	@Override
	public void deleteList(List<Serializable> idList) {
		// TODO Auto-generated method stub
		for (Serializable id : idList) {
			 delete(id);
		}
	}

}
